﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
using System.Windows.Forms;
using HalconDotNet;
using Go;

namespace fhs
{
    static class VisionInit
    {
        static private work_engine calcWord = functional.init(delegate ()
        {
            work_engine eng = new work_engine();
            eng.run(1, System.Threading.ThreadPriority.Normal, true);
            eng.service.post(delegate ()
            {
                HTuple computeDevices;
                HOperatorSet.QueryAvailableComputeDevices(out computeDevices);
                string[] operators = VisionInit.ComputeOperators();
                int dev = VisionInit.ComputeDevice();
                if (computeDevices.Length > 0 && operators.Length > 0 && dev >= 0)
                {
                    LogMgr.Info($"找到{computeDevices.Length}个硬件加速设备");
                    HTuple deviceHandle;
                    try
                    {
                        HOperatorSet.OpenComputeDevice(computeDevices[dev], out deviceHandle);
                        HOperatorSet.SetComputeDeviceParam(deviceHandle, "asynchronous_execution", "false");
                    }
                    catch (System.Exception)
                    {
                        LogMgr.Error("硬件加速初始化错误");
                        return;
                    }
                    for (int i = 0; i < operators.Length; i++)
                    {
                        try
                        {
                            HOperatorSet.InitComputeDevice(deviceHandle, operators[i]);
                        }
                        catch (System.Exception)
                        {
                            LogMgr.Error($"硬件加速初始化错误 {operators[i]}");
                        }
                    }
                    HOperatorSet.ActivateComputeDevice(deviceHandle);
                }
            });
            return eng;
        });

        static public Task ACalc(Action action)
        {
            return generator.send_service(calcWord.service, action);
        }

        static public void Calc(Action action)
        {
            Exception hasExcep = null;
            Monitor.Enter(calcWord);
            calcWord.service.post(delegate ()
            {
                try
                {
                    action();
                }
                catch (System.Exception ec)
                {
                    hasExcep = ec;
                }
                Monitor.Enter(calcWord);
                Monitor.Pulse(calcWord);
                Monitor.Exit(calcWord);
            });
            Monitor.Wait(calcWord);
            Monitor.Exit(calcWord);
            if (null != hasExcep)
            {
                throw hasExcep;
            }
        }

        static private int ComputeDevice()
        {
            return DefaultLoad.Load(-1, "./Config/ComputeDevice.txt", 0);
        }

        static private string[] ComputeOperators()
        {
            return new string[]
            {
                "find_ncc_model"
            };
        }


        static public bool Init(VisionName.Vision name, out VisionBase vision, out Form visionForm)
        {
            vision = null;
            visionForm = null;
            try
            {
                switch (name)
                {
                    case VisionName.Vision.Temp:
                        break;
                    case VisionName.Vision.Line:
                        vision = new Vision_Line();
                        visionForm = new VisionParamForm_Line();
                        return true;
                    case VisionName.Vision.Mark:
                        vision = new Vision_Mark();
                        visionForm = new VisionParamForm_Mark();
                        return true;
                    case VisionName.Vision.Calib:
                        vision = new Vision_Calib();
                        visionForm = new VisionParamForm_Calib();
                        return true;
                    default:
                        LogMgr.Error($"{name} 视觉算法未实现");
                        break;
                }
            }
            catch (System.Exception)
            {
                LogMgr.Error($"初始化 {name} 视觉参数异常");
            }
            return false;
        }
    }
}
